Skip to content

Support RFC 9802 LMS and XMSS in X.509 certificate and CSR generation#21

Closed
Frauschi wants to merge 1 commit into
masterfrom
claude/lms-xmss-cert-generation-vYWUq
Closed

Support RFC 9802 LMS and XMSS in X.509 certificate and CSR generation#21
Frauschi wants to merge 1 commit into
masterfrom
claude/lms-xmss-cert-generation-vYWUq

Conversation

@Frauschi
Copy link
Copy Markdown
Owner

@Frauschi Frauschi commented Jun 2, 2026

Overview

Builds on the existing RFC 9802 LMS/XMSS X.509 verification support by wiring HSS/LMS and XMSS/XMSS^MT keys into the certificate and PKCS#10 certificate-request generation API. These stateful hash-based schemes follow the same "sign the message directly, no pre-hash" pattern already used for Falcon / ML-DSA / SLH-DSA.

CSR support is included (per design discussion): cert signing and CSR proof-of-possession share the same MakeSignature() dispatch, and there's no reason to special-case CSRs out. The only caveat — each cert and each CSR consumes one of the key's finite one-time signatures — is inherent to the scheme and documented at the API surface.

Public API

  • New CertType selectors LMS_TYPE, XMSS_TYPE, XMSSMT_TYPE accepted by wc_MakeCert_ex, wc_SignCert_ex and wc_MakeCertReq_ex.
  • New cert_enums values LMS_KEY, XMSS_KEY, XMSSMT_KEY.
  • New wc_LmsKey_PublicKeyToDer / wc_XmssKey_PublicKeyToDer encoders that emit the RFC 9802 SubjectPublicKeyInfo via the existing SetAsymKeyDerPublic helper and the already-registered HSS_LMSk / XMSSk / XMSSMTk key OIDs.
  • Callers set cert->sigType to CTC_HSS_LMS / CTC_XMSS / CTC_XMSSMT.
LmsKey key; Cert cert; byte der[8192];
wc_LmsKey_Init(&key, heap, devId);
wc_LmsKey_SetParameters(&key, levels, height, winternitz);
wc_LmsKey_SetWriteCb/SetReadCb/SetContext(...);   /* persist state */
wc_LmsKey_MakeKey(&key, &rng);

wc_InitCert(&cert);
cert.sigType = CTC_HSS_LMS; cert.isCA = 1; cert.selfSigned = 1;
wc_MakeCert_ex(&cert, der, sizeof(der), LMS_TYPE, &key, &rng);
wc_SignCert_ex(cert.bodySz, cert.sigType, der, sizeof(der), LMS_TYPE, &key, &rng);

Implementation

  • Thread LmsKey*/XmssKey* through EncodePublicKey, MakeAnyCert, MakeCertReq, MakeSignature and SignCert (ASN.1 template path), mirroring the existing PQ-key plumbing.
  • SignCert sizes the signature buffer at runtime from wc_LmsKey_GetSigLen / wc_XmssKey_GetSigLen, since LMS/XMSS signatures are parameter-dependent and can exceed MAX_ENCODED_SIG_SZ. In WOLFSSL_NO_MALLOC builds (fixed-size buffer) an oversized signature fails cleanly with BUFFER_E rather than overflowing.
  • SignCert validates that sigType matches the key (LMS → CTC_HSS_LMS; XMSS → CTC_XMSS/CTC_XMSSMT per is_xmssmt), and the XMSS_TYPE/XMSSMT_TYPE selector is validated against the key's tree variant — so a mismatch returns an error instead of silently emitting a malformed certificate.
  • Forward-declare LmsKey/XmssKey in asn_public.h (guarded typedefs in wc_lms.h/wc_xmss.h) so the shared signatures compile regardless of feature macros.
  • Enable WC_ENABLE_ASYM_KEY_EXPORT/IMPORT for non-verify-only LMS/XMSS builds so the SPKI encoder is compiled.
  • LMS/XMSS cert generation is template-only (the original/non-template path has no LMS/XMSS support, consistent with verification); the non-template MakeAnyCert/MakeCertReq emit a clear diagnostic and ALGO_ID_E if handed such a key.

Tests

test_rfc9802_lms_x509_gen / test_rfc9802_xmss_x509_gen generate a self-signed root CA and a PKCS#10 CSR, then verify the cert via wolfSSL_CertManagerVerifyBuffer and the CSR proof-of-possession via wc_ParseCert. Coverage includes single-level LMS, multi-level HSS (L2), single-tree XMSS, and XMSS^MT, plus negative cases for sigType/keyType and selector mismatches.

Notes / scope

  • No interop test: OpenSSL still lacks LMS/XMSS X.509 certificate signing (XMSS & LMS openssl/openssl#21360), and Bouncy Castle's encoding is not yet aligned with the final RFC 9802 — so there is no aligned third-party implementation to interoperate against.
  • Verified across full, WOLFSSL_ASN_ORIGINAL (non-template), and verify-only LMS/XMSS builds; the API test suite passes with 0 failures, and testwolfcrypt passes.

https://claude.ai/code/session_01RDkoNViK5aNkUAJqnuL8Y5


Generated by Claude Code

Comment thread wolfssl/wolfcrypt/asn_public.h Outdated
Comment thread wolfcrypt/src/asn_orig.c Outdated
Comment thread wolfcrypt/src/asn.c Outdated
Comment thread wolfcrypt/src/asn.c Outdated
Comment thread wolfcrypt/src/asn.c
Comment thread certs/xmss/include.am Outdated
certs/xmss/bc_xmssmt_sha2_40_8_256_root.der \
certs/xmss/bc_xmss_chain_ca.der \
certs/xmss/bc_xmss_chain_leaf.der
# No committed XMSS X.509 fixtures: there is no RFC 9802-aligned third-party
Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we simply remove the file and the directory instead?

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done — removed certs/xmss/include.am entirely and dropped its include certs/xmss/include.am line from certs/include.am, so the certs/xmss/ directory is gone rather than kept as an empty file.

Note this was folded into the rebase onto the updated master: upstream had moved the LMS/XMSS tests out of tests/api.c into tests/api/test_lms_xmss.c, so I re-homed all the generation test work there (api.c is now unchanged from upstream) and resolved the conflict that way. Force-pushed the rebased branch.


Generated by Claude Code

@Frauschi Frauschi force-pushed the claude/lms-xmss-cert-generation-vYWUq branch from 0aab291 to f14a143 Compare June 2, 2026 12:13
Extend wc_MakeCert_ex/wc_SignCert_ex/wc_MakeCertReq_ex to issue HSS/LMS and
XMSS/XMSS^MT certificates and PKCS#10 requests, building on the existing
RFC 9802 verification support. New LMS_TYPE/XMSS_TYPE/XMSSMT_TYPE selectors,
wc_{Lms,Xmss}Key_PublicKeyToDer SPKI encoders, runtime signature-buffer
sizing, and sigType/key consistency checks. Generation is ASN.1-template
only, matching where the verification path lives.

Tests generate self-signed roots, CSRs and a CA->ECC-leaf chain in-process
and verify them, replacing the patched Bouncy Castle fixtures (only the stock
RFC 9802-aligned LMS interop anchor is kept).

https://claude.ai/code/session_01RDkoNViK5aNkUAJqnuL8Y5
@Frauschi Frauschi force-pushed the claude/lms-xmss-cert-generation-vYWUq branch from f14a143 to b663393 Compare June 2, 2026 12:18
@Frauschi Frauschi closed this Jun 2, 2026
@Frauschi Frauschi deleted the claude/lms-xmss-cert-generation-vYWUq branch June 2, 2026 12:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants